package test29.Lambda;

import org.junit.Test;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.function.Consumer;

/**
 * 总结
 * ->左边：lambda形参列表的参数类型可用省略（类型推断）；如果lambda参数列表只有一个参数，其一对（）也可以省略
 * ->右边：lambda体应该使用一队{}包裹；如果lambda体只有一条执行语句（可能是return语句），可用省略这一对{}和return关键字
 *
 * lambda表达式本质：作为接口的实例（lambda都是针对接口，接口只能有一个方法，接口要求：函数式接口）
 * lambda表达式本质：作为函数式接口的实例
 *
 * 如果一个接口中，只声明了一个抽象方法，则此接口就称为函数式接口，我们可以在一个接口上使用@FunctionalInterface注解，这样做可以检
 * 查它是否是一个函数式接口。
 *  所以以前用匿名实现类表示的现在都可以用Lambda表达式来写
 *
 * 上联：左右遇一括号省
 * 下联：左侧推断类型省
 * 横批：能省则省
 */
public class LambdaTest {
    @Test
//	语法格式一：无参数，无返回值
    public void test1() {
        int num = 0;//jdk 1.7 前，必须是 final

        Runnable r = new Runnable() {
            @Override
            public void run() {
                System.out.println("Hello World!" + num);
            }
        };

        r.run();

        System.out.println("-------------------------------");

        Runnable r1 = () -> {
            System.out.println("Hello Lambda!");
        };
        r1.run();
    }

    @Test
//	语法格式二：有一个参数，并且无返回值
    public void test2() {
        Consumer<String> consumer = new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        };
        consumer.accept("s");

        System.out.println("==============================");
        Consumer<String> con = (String s) -> {
            System.out.println(s);
        };
        con.accept("我大尚硅谷威武！");
    }

    @Test
//    语法格式三:因为可由编译器推断得出，称为“类型推断数据类型可以省略，
//    Lambda 表达式的参数列表的数据类型可以省略不写，因为JVM编译器通过上下文推断出，数据类型，即“类型推断”
    public void test3() {
        Consumer<String> con = (String s) -> {
            System.out.println(s);
        };
        con.accept("我大尚硅谷威武！");

        System.out.println("================");
        Consumer<String> con2 = (s) -> {
            System.out.println(s);
        };
        con2.accept("喜欢");
    }

    @Test
    public void test4() {
        ArrayList<String> list = new ArrayList<>();  //类型推断
        int[] arr = {1, 2, 3}; //类型推断
    }

    @Test
//    语法格式四：Lambda若只有一个参数，小括号可以省略不写
    public void test5() {
        Consumer<String> con2 = (s) -> {
            System.out.println(s);
        };
        con2.accept("喜欢");
        System.out.println("=================");
        Consumer<String> con3 = s -> {
            System.out.println(s);
        };
    }

    @Test
//    语法格式五：有两个以上的参数，有返回值，并且 Lambda 体中有多条语句
    public void test6() {
        Comparator<Integer> com1 = new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                System.out.println(o1);
                return o1.compareTo(o2);
            }
        };
        System.out.println(com1.compare(12, 21));

        System.out.println("===================");
        Comparator<Integer> com2 = (o1, o2) -> {
            System.out.println(o1);
            System.out.println(o2);
            return o1.compareTo(o2);
        };
        System.out.println(com2.compare(12, 6));
    }

    // 语法格式六：若 Lambda 体中只有一条语句， return 和 大括号都可以省略不写
    @Test
    public void test7() {
        Comparator<Integer> com1 = (o1, o2) -> {
            return o1.compareTo(o2);
        };
        System.out.println(com1.compare(12, 6));

        System.out.println("===================");
        Comparator<Integer> com2 = (o1, o2) -> o1.compareTo(o2);
        System.out.println(com2.compare(12, 6));
    }

    @Test
    public void test8(){
        Consumer<String> con3 = s -> {
            System.out.println(s);
        };
        con3.accept("一个愿打一个愿挨");

        System.out.println("==============");
        Consumer<String> con4 = s -> System.out.println(s);
        con4.accept("挨打");
    }
}
